package tech.cn.note.word;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Map;

import javax.annotation.PostConstruct;

import cn.hutool.json.JSONUtil;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import tech.cn.note.utils.CheckUtil;
import tech.cn.note.word.fun.RenderFunction;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
@Slf4j
@RequiredArgsConstructor
public class PoiTemplateDataFillServiceImpl {

    private static Configure configure;

    private static final ConfigureBuilder builder = Configure.builder();

    private final Map<String, RenderFunction> strategyMap;

    @Value("${custom.nullError:false}")
    private Boolean nullError;

    public static final ThreadLocal threadLocal = new ThreadLocal();

    @PostConstruct
    private void init() {
        builder.buildGramer("${", "}");
        builder.useSpringEL(false);
        builder.addPlugin('~', new LoopRowTableRenderPolicy());
        builder.addPlugin('%', new StrongRenderPolicy(strategyMap));
        builder.addPlugin('\u0000', new CustomTextRenderPolicy());
        configure = builder.build();
    }

    public byte[] writeToByte(Map<String, Object> valueMap, byte[] templateFileBytes) throws Exception {
        try {
            CheckUtil.checkNotNull(templateFileBytes, "模板文件不能为空");
            CheckUtil.checkNotNull(valueMap, "数据源为空");
            XWPFTemplate template = prepare(new ByteArrayInputStream(templateFileBytes), valueMap);
            //如果需要输出PDF则进行转换
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            template.write(byteArrayOutputStream);
            return byteArrayOutputStream.toByteArray();
        } finally {
            threadLocal.remove();
        }
    }

//    public byte[] writeToByte(DocumentFillDTO documentFillDTO) throws Exception {
//        try {
//            Map<String, Object> valueMap = documentFillDTO.getValueMap();
//            byte[] templateFileBytes = documentFillDTO.getTemplateFileBytes();
//            CheckUtil.checkNotNull(templateFileBytes, "模板文件不能为空");
//            CheckUtil.checkNotNull(valueMap, "数据源为空");
//            XWPFTemplate template = prepare(new ByteArrayInputStream(templateFileBytes), valueMap);
//            //如果需要输出PDF则进行转换
//            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//            template.write(byteArrayOutputStream);
//            if (FileType.PDF == documentFillDTO.getFileType()) {
//                return FileUtil.doPdfProcessByAsposeOfWord(byteArrayOutputStream.toByteArray());
//            } else {
//                return byteArrayOutputStream.toByteArray();
//            }
//        } finally {
//            threadLocal.remove();
//        }
//    }

//    public String writeToString(DocumentFillDTO documentFillDTO) throws Exception {
//        try {
//            Map<String, Object> valueMap = documentFillDTO.getValueMap();
//            byte[] templateFileBytes = documentFillDTO.getTemplateFileBytes();
//            CheckUtil.checkNotNull(templateFileBytes, "模板文件不能为空");
//            CheckUtil.checkNotNull(valueMap, "数据源为空");
//            XWPFTemplate template = prepare(new ByteArrayInputStream(templateFileBytes), valueMap);
//            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//            template.write(byteArrayOutputStream);
//            XWPFDocument document = new XWPFDocument(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
//            XWPFWordExtractor extractor = new XWPFWordExtractor(document);
//            return extractor.getText();
//        } finally {
//            StrongRenderPolicy.threadLocal.remove();
//        }
//    }

    /**
     * poi-tl框架填充数据
     *
     * @param inputStream 模板字节文件流
     * @param map         数据源
     * @return 填充结束的XWPFTemplate
     */
    private XWPFTemplate prepare(ByteArrayInputStream inputStream, Map<String, Object> map) {
        if (nullError) {
            builder.setValidErrorHandler(new Configure.AbortHandler());
        } else {
            builder.setValidErrorHandler(new Configure.ClearHandler());
        }
        configure = builder.build();
        log.debug("data is {}", JSONUtil.parse(map));
        threadLocal.set(map);
        return XWPFTemplate.compile(inputStream, configure).render(map);
    }

}
